package com.hsmpay.mobile.action.account.officialAccPay;

import com.hsmpay.common.pojo.qian4.Qian4SendLog;
import com.hsmpay.common.pojo.user.User;
import com.hsmpay.common.util.DateConvertUtil;
import com.hsmpay.common.util.OrderTypeUtil;
import com.hsmpay.common.util.URLDecoderTools;
import com.hsmpay.mobile.action.account.qian48.Q4BaseAction;
import com.hsmpay.mobile.action.account.scanCodePay.ScanCodePayParam;
import com.hsmpay.mobile.pojo.terminal.Tchannel;
import com.hsmpay.mobile.pojo.trans.TransOrder;
import com.hsmpay.mobile.pojo.trans.TransPriorSettle;
import com.hsmpay.mobile.service.trans.TransPriorSettleService;
import com.hsmpay.qian4.pojo.PurchaseResult;
import com.hsmpay.utils.TimeUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class OfficialAccPayBaseAction extends Q4BaseAction {
    private static final long serialVersionUID = 4841990981226162770L;
    private static Logger log = Logger.getLogger(OfficialAccPayBaseAction.class);

    public static final String SCANCODEPAY_FUNCKEY = "SCANCODEPAY";
    public final static int TC_XY = 83;//兴业银行扫码支付
    public final static int TC_JQ = 84;//进钱支付
    public final static int TC_WEIXIN = 85;//微信支付
    public final static int TC_SHANGLIANCHU = 86;//商联储
    public final static int TC_JQ_SECOND = 87;//进钱秒到
    public final static int TC_JQ_QR = 89;//进钱二维码
    public final static int TC_HSM = 99;//花生米对外接口
    public final static int TC_JQ_SDK = 90;//进钱SDK

    //扫码支付
    protected String authCode; //这个是扫码终端设备从用户手机上扫取到的支付授权号，这个号是跟用户用来支付的银行卡绑定的，有效期是1分钟
    protected String body; //要支付的商品的描述信息，用户会在支付成功页面里看到这个信息
    protected String attach; //支付订单里面可以填的附加数据，API会将提交的这个附加数据原样返回
    protected String outTradeNo; //商户系统内部的订单号,32个字符内可包含字母, 确保在商户系统唯一
    protected String totalFee; //订单总金额，单位为“分”，只能整数
    protected String deviceInfo; //商户自己定义的扫码支付终端设备号，方便追溯这笔交易发生在哪台终端设备上
    protected String spBillCreateIP; //订单生成的机器IP
    protected String timeStart; //订单生成时间， 格式为yyyyMMddHHmmss，如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器
    protected String timeExpire; //订单失效时间，格式同上
    protected String goodsTag; //商品标记
    protected String subOpenId;
    protected String openId;

    @Resource(name = "transPriorSettleService")
    public TransPriorSettleService<TransPriorSettle, Long> transPriorSettleService;

    protected Object[] assembleBean(User user) throws Exception {
        clientType = user.getClientType();
        terminalTypeId = user.getTerminalTypeId();
        roleId = user.getRoleId();

        merchantOrderId = getWechartString("merchantOrderId");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        merchantOrderTime = sdf.format(new Date());
        functionKey = SCANCODEPAY_FUNCKEY;

        authCode = getWechartString("authCode");
        body = getWechartString("body");
        attach = getWechartString("attach");
        outTradeNo = getWechartString("outTradeNo");
        deviceInfo = getWechartString("deviceInfo");
        spBillCreateIP = getWechartString("spBillCreateIP");
        timeStart = getWechartString("timeStart");
        timeExpire = getWechartString("timeExpire");
        goodsTag = getWechartString("goodsTag");
        subOpenId = getWechartString("openId");

        if (null == user.getTerminalTypeId()) {
            log.warn("支付时, 传入参数terminalTypeId为空");
            sendWeChatErrorMsg("6001", "terminalTypeId");
            return null;
        }

        if (null == totalFee) {
            log.warn("支付时, totalFee为空");
            sendWeChatErrorMsg("6001", "totalFee");
            return null;
        }


        //判断日期是否是今天
        Date date = new Date();
        String today = DateConvertUtil.dateString(date, "yyyyMMdd");
        if (!merchantOrderTime.startsWith(today)) {
            merchantOrderId = getMerchantOrderId(date, user.getLoginName());
            merchantOrderTime = DateConvertUtil.dateString(date, "yyyyMMddHHmmss");
        }

        //查出商户订单号 是否存在
        TransOrder transOrder = transOrderService.searchOrderByMerchantOrderId(user.getLoginName(), merchantOrderId);
        if (null != transOrder) {
            sendWeChatErrorMsg("6101", merchantOrderId);
            return null;
        }

        //组装 发送数据
        Qian4SendLog send = new Qian4SendLog();
        send.setCallType(0);
        send.setUserId(user.getId());
        send.setOrderTypeId(RECEIVABLES);
        send.setApplication("OfficialAccPay.Req");
        send.setTransType("100001");//
        send.setSendTime(date);
        send.setSendSeqId(TimeUtils.getTimeToString());
        send.setTerminalId(terminalId);
        send.setPlatformId(platformId);
        send.setRoleId(user.getId());

        send.setMerchantOrderId(merchantOrderId);//商户订单号
        send.setMerchantOrderTime(DateConvertUtil.stringDate(merchantOrderTime, "yyyyMMddHHmmss"));//商户订单号时间
        send.setTransTime(send.getSendTime());
        send.setTransAmt(totalFee);
        send.setCurrency("156");
        send.setIp(URLDecoderTools.getRemoteHost(getRequest()));//IP
        send.setCardTypeN(4);

        transOrder = new TransOrder();
        transOrder.setOrderNum(genOrderNo(user.getChannelId()));
        transOrder.setOrderTypeId(RECEIVABLES);//我要收款
        transOrder.setUserId(user.getId());
        transOrder.setPUserId(user.getPUserId());//父用户Id
        transOrder.setTransMoney(Double.parseDouble(totalFee));
        transOrder.setRootCategory("账务管理");
        transOrder.setCategory(OrderTypeUtil.RECEIVABLES_STR);
        transOrder.setBankCard(accountNumber);
        transOrder.setObjectiveName(StringUtils.isBlank(user.getCardholder()) ? user.getUserName() : user.getCardholder());//user.getUserName());//对方持卡人姓名
        transOrder.setObjectiveCard(user.getBankCard());//对方银行卡
        transOrder.setObjectiveOpBank(user.getOpeningBank());//对方银行
        transOrder.setStatus(3);//交易状态  0交易失败 1交易成功 2银行交易处理中 3 未付款 4等待对方付款 5关闭交易
        transOrder.setClearing(0);//结算状态 0未结算 1结算
        transOrder.setCreateDate(date);
        transOrder.setUpdateLongTime(date.getTime());

        transOrder.setObjectiveBBank(user.getBranchesBank());//对方银行支行
        transOrder.setObjectiveBBProvince(user.getBBankProvince());
        transOrder.setObjectiveBBCity(user.getBBankCity());
        transOrder.setObjectiveMobile(user.getMobile());//对方手机号
        transOrder.setObjectiveBBankCode(user.getBranchesBankCode());//支行Code
        transOrder.setTerminalTypeId(user.getTerminalTypeId());
        transOrder.setRoleId(user.getRoleId());
        transOrder.setCardTypeN(send.getCardTypeN());//1 磁条卡 2 IC卡 3无卡 4扫码
        transOrder.setClientType(user.getClientType());
        
        Double feeRate = user.getFeeRate();

        transOrder.setFeeRate(feeRate);//用户费率

        ScanCodePayParam scanCodePayParam = new ScanCodePayParam();
        scanCodePayParam.setAuthCode(authCode);
        scanCodePayParam.setBody(user.getNickName());
        scanCodePayParam.setAttach(attach);
        scanCodePayParam.setOutTradeNo(transOrder.getOrderNum());
        scanCodePayParam.setTotalFee(totalFee);
        scanCodePayParam.setDeviceInfo(deviceInfo);
        scanCodePayParam.setSpBillCreateIP(spBillCreateIP);
        scanCodePayParam.setTimeStart(timeStart);
        scanCodePayParam.setTimeExpire(timeExpire);
        scanCodePayParam.setGoodsTag(goodsTag);
        scanCodePayParam.setOpenId(openId);
        scanCodePayParam.setSubOpenId(subOpenId);

        Object[] resultA = new Object[3];
        resultA[0] = send;
        resultA[1] = transOrder;
        resultA[2] = scanCodePayParam;
        return resultA;
    }

    /**
     * 返回
     * @param pr
     * @param transOrder
     * @param transPriorSettle
     * @param user
     * @param tc
     * @return
     * @throws Exception
     */
    protected JSONObject purchaseResolveResult(Qian4SendLog send, PurchaseResult pr, TransOrder transOrder, TransPriorSettle transPriorSettle, User user, Tchannel tc) throws Exception {
        JSONObject result = new JSONObject();
        if (0 == pr.getStatus()) {//错误
            log.debug("交易失败!");
            result.put("bankResp", "0");
            result.put("reqCode", pr.getReqCode());
            result.put("msg", pr.getReqMsg());
            accountManageQ4Service.receivablesError(transPriorSettle, pr.getReqCode(), pr.getReqMsg());
            qian4SendLogService.updateResCodeMassage(transPriorSettle.getSendId(), pr.getReqCode(), pr.getReqMsg());

        } else {
            transPriorSettle = accountManageQ4Service.purchaseResolveResult(transPriorSettle, send, pr, tc, user.getOrganizationId());

            result.put("bankResp", "1");
            result.put("status", transOrder.getStatus());
            result.put("orderNum", transOrder.getOrderNum());
            result.put("transTime", DateConvertUtil.dateString(transOrder.getCreateDate(), "HH:mm:ss"));
            result.put("terminalId", transPriorSettle.getTerminalId());//终端编号
            result.put("expireDate", null == transPriorSettle.getExpireDate() ? "" : transPriorSettle.getExpireDate());//卡有效期（预授权时）
            result.put("transMoney", transOrder.getTransMoney());//交易金额
            result.put("merchantOrderId", transPriorSettle.getMerchantOrderId());
        }
        return result;
    }

    /**
     * 撤销超时
     * @return
     * @throws Exception
     */
    public Map<String, Object> revocationOrderTimeOut(Qian4SendLog recSend, TransPriorSettle transPriorSettle, ScanCodePayParam scanCodePayParam) throws Exception {

        Date date = new Date();
        Qian4SendLog send = new Qian4SendLog();
        send.setCallType(0);
        send.setUserId(recSend.getUserId());
        send.setApplication("Void.Req");
        send.setOrderTypeId(OrderTypeUtil.REVOCATION);
        send.setSendTime(date);
        send.setRoleId(recSend.getRoleId());
        send.setSendSeqId(TimeUtils.getTimeToString());
        send.setTransType("200000");//200000：撤销

        send.setMerchantOrderId(DateConvertUtil.dateString(date, "yyyyMMddHHmmssSSS"));
        send.setMerchantOrderTime(DateConvertUtil.stringDate(merchantOrderTime, "yyyyMMddHHmmss"));
        send.setTransTime(send.getSendTime());
        send.setOrgTransId(recSend.getBankOrderNum());//原订单号
        send.setOrgTransTime(recSend.getMerchantOrderTime());//原订单时间
        send.setOrgMerchantOrderId(recSend.getMerchantOrderId());
        send.setTransAmt(recSend.getTransAmt());

        send.setMerchantSign(recSend.getMerchantSign());
        send.setSenderSign(recSend.getSenderSign());
        send.setServiceInfo(recSend.getServiceInfo());
        send.setTerminalInfo(recSend.getTerminalInfo());

        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("status", 0);
        try {
            resultMap = accountManageQ4Service.isCanRevocationOrder(send);
            int status = (Integer) resultMap.get("status");
            if (status == 1) {
                TransOrder transOrder = new TransOrder();
                transOrder.setOrderNum(transPriorSettle.getOrderNum());
                transOrder = transOrderService.searchEntity(transOrder);
                if (transOrder.getStatus().intValue() == 1) {
                    if (null != transPriorSettle.getStatus() && 1 == transPriorSettle.getStatus().intValue()) {
                        //查询订单 修改金额
                        accountManageQ4Service.updateUserMoney(transOrder, 0, transOrder.getChargeAmount());
                    }
                }
                transOrderService.updateStatusClearing(transPriorSettle.getOrderNum(), 7, null);//发起撤销
                transPriorSettle = transPriorSettleService.searchTransPriorSettle(send.getTerminalId(), send.getOrgMerchantOrderId());
                date = new Date();
                send.setMerchantOrderId(DateConvertUtil.dateString(date, "yyyyMMddHHmmssSSS"));
                send.setMerchantOrderTime(date);
                long sendId = qian4SendLogService.insertEntity(send);
                send.setId(sendId);
                //真正去冲正的方法
                resultMap = accountManageQ4Service.scanRevocationOrder(send,scanCodePayParam);
                int flag = (Integer) resultMap.get("status");
                if (flag == 0 && (send.timeOut == 1 || send.timeOut == 2 || send.timeOut == 3)) {
                    resultMap = revocationOrderTimeOut(recSend, transPriorSettle,scanCodePayParam);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultMap;
    }

    //----------------------------------------getter and setter-------------------------------------

    public String getAuthCode() {
        return authCode;
    }

    public void setAuthCode(String authCode) {
        this.authCode = authCode;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getAttach() {
        return attach;
    }

    public void setAttach(String attach) {
        this.attach = attach;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public void setOutTradeNo(String outTradeNo) {
        this.outTradeNo = outTradeNo;
    }

    public String getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(String totalFee) {
        this.totalFee = totalFee;
    }

    public String getDeviceInfo() {
        return deviceInfo;
    }

    public void setDeviceInfo(String deviceInfo) {
        this.deviceInfo = deviceInfo;
    }

    public String getSpBillCreateIP() {
        return spBillCreateIP;
    }

    public void setSpBillCreateIP(String spBillCreateIP) {
        this.spBillCreateIP = spBillCreateIP;
    }

    public String getTimeStart() {
        return timeStart;
    }

    public void setTimeStart(String timeStart) {
        this.timeStart = timeStart;
    }

    public String getTimeExpire() {
        return timeExpire;
    }

    public void setTimeExpire(String timeExpire) {
        this.timeExpire = timeExpire;
    }

    public String getGoodsTag() {
        return goodsTag;
    }

    public void setGoodsTag(String goodsTag) {
        this.goodsTag = goodsTag;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public String getSubOpenId() {
        return subOpenId;
    }

    public void setSubOpenId(String subOpenId) {
        this.subOpenId = subOpenId;
    }
}

